package com.netsdk.utils;

import com.netsdk.common.Res;
import com.netsdk.demo.module.LoginModule;
import com.netsdk.lib.NetSDKLib;
import com.netsdk.lib.ToolKits;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.nio.ByteBuffer;

/**
 * 初始化
 *
 * @author Yan Xu
 * @version 1.0
 * @date 2021/8/6
 * Copyright © goodits
 */
@Component
@Slf4j
public class InitUtils {

    /**
     * // 设备断线回调: 通过 CLIENT_Init 设置该回调函数，当设备出现断线时，SDK会调用该函数
     */
    private static class DisConnect implements NetSDKLib.fDisConnect {
        @Override
        public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
            log.info("Device[{}}] Port[{}}] DisConnect!\n", pchDVRIP, nDVRPort);
            // 断线提示
            log.info(Res.string().getFaceRecognition() + " : " + Res.string().getDisConnectReconnecting());
        }
    }

    /**
     * // 网络连接恢复，设备重连成功回调
     * // 通过 CLIENT_SetAutoReconnect 设置该回调函数，当已断线的设备重连成功时，SDK会调用该函数
     */
    private static class HaveReConnect implements NetSDKLib.fHaveReConnect {
        @Override
        public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
            log.info("ReConnect Device[{}] Port[{}]\n", pchDVRIP, nDVRPort);
            // 重连提示
            log.info(Res.string().getFaceRecognition() + " : " + Res.string().getOnline());
        }
    }


    /**
     * 写成静态主要是防止被回收
     */
    private static class AnalyzerDataCB implements NetSDKLib.fAnalyzerDataCallBack {
        private AnalyzerDataCB() {
        }

        public static AnalyzerDataCB INSTANCE = new AnalyzerDataCB();

        public static AnalyzerDataCB getInstance() {
            return INSTANCE;
        }

        public int invoke(
                NetSDKLib.LLong lAnalyzerHandle,
                int dwAlarmType,
                Pointer pAlarmInfo,
                Pointer pBuffer,
                int dwBufSize,
                Pointer dwUser,
                int nSequence,
                Pointer reserved) {
            if (lAnalyzerHandle.longValue() == 0 || pAlarmInfo == null) {
                return -1;
            }

            switch (dwAlarmType) {

                case NetSDKLib.EVENT_IVS_ACCESS_CTL:// /< 门禁事件
                {
                    NetSDKLib.DEV_EVENT_ACCESS_CTL_INFO msg = new NetSDKLib.DEV_EVENT_ACCESS_CTL_INFO();
                    ToolKits.GetPointerData(pAlarmInfo, msg);
                    // 获取门禁信息
                    //打印msg中的卡信息和用戶信息
                    int szCardNo = ByteBuffer.wrap(msg.szCardNo).getInt();
                    System.out.println("卡号：" + szCardNo);
                    int szUserId = ByteBuffer.wrap(msg.szUserID).getInt();
                    System.out.printf("用户ID：%d\n", szUserId);

                    log.info("门禁事件：卡号：{}，用户ID：{}", szCardNo, szUserId);
                    // 释放内存
                    msg = null;
                    System.gc();

                    break;
                }
                case NetSDKLib.EVENT_IVS_FACERECOGNITION: // /< 人脸识别事件
                {
                    // DEV_EVENT_FACERECOGNITION_INFO 结构体比较大，new对象会比较耗时， ToolKits.GetPointerData内容拷贝是不耗时的。
                    // 如果多台设备或者事件处理比较频繁，可以考虑将 static DEV_EVENT_FACERECOGNITION_INFO msg = new
                    // DEV_EVENT_FACERECOGNITION_INFO(); 改为全局。
                    // 写成全局，是因为每次new花费时间较多, 如果改为全局，此case下的处理需要加锁
                    // 加锁，是因为共用一个对象，防止数据出错

                    // 耗时800ms左右
                    NetSDKLib.DEV_EVENT_FACERECOGNITION_INFO msg = new NetSDKLib.DEV_EVENT_FACERECOGNITION_INFO();
                    // 耗时20ms左右
                    ToolKits.GetPointerData(pAlarmInfo, msg);
                    //todo 保存人脸对比信息

                    // 释放内存
                    msg = null;
                    System.gc();

                    break;
                }
                case NetSDKLib.EVENT_IVS_FACEDETECT: // /< 人脸检测
                {
                    NetSDKLib.DEV_EVENT_FACEDETECT_INFO msg = new NetSDKLib.DEV_EVENT_FACEDETECT_INFO();
                    ToolKits.GetPointerData(pAlarmInfo, msg);
                    //todo 保存图片，获取图片缓存

                    // 释放内存
                    msg = null;
                    System.gc();
                    break;
                }
                default:
                    break;
            }

            return 0;
        }
    }

    /**
     * 设备断线通知回调
     */
    private static final DisConnect DIS_CONNECT = new DisConnect(){};

    /**
     * 网络连接恢复
     */
    private static final HaveReConnect HAVE_RE_CONNECT = new HaveReConnect();


    @PostConstruct
    void init() {
       LoginModule.init(DIS_CONNECT, HAVE_RE_CONNECT);
    }
}
